package cn.deschen.common.exception;

import cn.deschen.common.api.CmRes;
import cn.deschen.common.api.CmResCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import javax.validation.ConstraintViolationException;
import java.util.Arrays;
import java.util.List;

/**
 * @Author hanbin_chen
 * @Description 全局异常处理
 * @DateTime 2021/6/1
 * @Version V1.0.0
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 对全局异常处理拦截
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = GlobalException.class)
    public CmRes<Object> globalExceptionHandler(GlobalException e) {
        if (e.getErrorCode() != null) {
            return CmRes.failure(e.getErrorCode(), e.getMessage(), e.getData());
        }
        return CmRes.failure(CmResCode.SYSTEM_ERROR, e.getMessage(), e.getData());
    }


    /**
     * 对绑定字段校验异常
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class,
            ConstraintViolationException.class, MissingServletRequestPartException.class})
    public CmRes<Void> paramExceptionHandler(Exception e) {
        String msg = "";
        if (e instanceof BindException) {
            BindException bindException = (BindException) e;
            List<ObjectError> errors = bindException.getAllErrors();
            ObjectError error = errors.get(0);
            msg = error.getDefaultMessage();
        } else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            BindingResult bindingResult = ex.getBindingResult();
            List<ObjectError> errors = bindingResult.getAllErrors();
            ObjectError error = errors.get(0);
            msg = error.getDefaultMessage();
        } else if (e instanceof ConstraintViolationException) {
            msg = e.getMessage().substring(e.getMessage().indexOf(":") + 1);
        } else if (e instanceof MissingServletRequestPartException) {
            msg = "文件不能为空";
        }
        return CmRes.failure(CmResCode.BIND_ERROR.extra(msg));
    }


    /**
     * 对全局异常处理拦截
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public CmRes<Void> exceptionHandler(Exception e) {
        log.error("MSG={} CAUSE={} STACK={}", "未知异常", e.toString(), Arrays.stream(e.getStackTrace()).toArray());
        return CmRes.failure(CmResCode.SYSTEM_ERROR, e.toString());
    }
}
